﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartMathLibrary.LinearEquationSolvers
{
    /// <summary>
    /// This class provides the solving of a complex linear system of equation by using the inverse matrix.
    /// </summary>
    [Serializable]
    public class InverseComplexLinearSystemSolver
    {
        /// <summary>
        /// Descripes if the solving of the system of equation has a precision error.
        /// </summary>
        private bool precisionError;

        /// <summary>
        /// The complex system of equation to solve.
        /// </summary>
        private readonly ComplexLinearEquationSystem equationSystem;

        /// <summary>
        /// Initializes a new instance of the <see cref="InverseComplexLinearSystemSolver"/> class.
        /// </summary>
        /// <param name="coefficientMatrix">The coefficient matrix of the equation system to solve.</param>
        /// <param name="resultVector">The result vector of the equation system to solve.</param>
        public InverseComplexLinearSystemSolver(ComplexMatrix coefficientMatrix, GeneralComplexVector resultVector)
        {
            this.equationSystem = new ComplexLinearEquationSystem(coefficientMatrix, resultVector);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="InverseComplexLinearSystemSolver"/> class.
        /// </summary>
        /// <param name="equationSystem">The system of equation to solve.</param>
        public InverseComplexLinearSystemSolver(ComplexLinearEquationSystem equationSystem)
        {
            if (equationSystem == (ComplexLinearEquationSystem) null)
            {
                throw new ArgumentNullException("equationSystem");
            }

            this.equationSystem = equationSystem;
        }

        /// <summary>
        /// Gets or sets the coefficient matrix of the equation system to solve.
        /// </summary>
        /// <value>The coefficient matrix of the equation system to solve.</value>
        public ComplexMatrix CoefficientMatrix
        {
            get { return equationSystem.CoefficientMatrix; }
            set { equationSystem.CoefficientMatrix = value; }
        }

        /// <summary>
        /// Gets or sets the result vector of the equation system to solve.
        /// </summary>
        /// <value>The result vector of the equation system to solve.</value>
        public GeneralComplexVector ResultVector
        {
            get { return equationSystem.ResultVector; }
            set { equationSystem.ResultVector = value; }
        }

        /// <summary>
        /// Descripes if the solving of the system of equation has a precision error. If the return value is true, 
        /// the computed results may be incorrect.
        /// </summary>
        public bool PrecisionError
        {
            get { return precisionError; }
        }

        /// <summary>
        /// Solves the linear system of equation by using the inverse matrix of the coefficient matrix.
        /// </summary>
        /// <returns>The results of the system of equation.</returns>
        public GeneralComplexVector SolveLinearSystem()
        {
            this.precisionError = false;

            if (!(this.CoefficientMatrix.Rows == this.CoefficientMatrix.Columns))
            {
                throw new ArgumentException(
                    "The coefficient matrix of the system of equation has to be a square matrix.");
            }

            ComplexMatrix inverse = new ComplexMatrix(this.CoefficientMatrix.Rows, this.CoefficientMatrix.Columns);

            try
            {
                inverse = ComplexInverseMatrix.FromMatrix(this.CoefficientMatrix);
            }
            catch
            {
                this.precisionError = true;
            }

            return inverse * this.ResultVector;
        }
    }
}